package net;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.util.CharsetUtil;

import data.ISerializable;

public class Protocol {
	public static final byte TYPE_INT = 0;
	public static final byte TYPE_STRING = 1;
	public static final byte TYPE_OBJECT= 2;
	public static final byte TYPE_INT_ARRAY = 3;
	public static final byte TYPE_STRING_ARRAY = 4;
	public static final byte TYPE_OBJECT_ARRAY = 5;
	public static final byte TYPE_BYTE = 8;
	
	public static final int HEAD_LENGTH = 4;
	public static final int DATA_LENGTH_MAX = 65536;
	
	public static final byte COMMAND_RPC = 1;
	public static final byte COMMAND_QUERY_RESULT = 2;
	
	public static final byte BOOL_TRUE = 1;
	public static final byte BOOL_FALSE = 0;
	
	public static String readString(ChannelBuffer data) {
		int len = data.readShort();
		int index = data.readerIndex();
		String str = data.toString(data.readerIndex(), len, CharsetUtil.UTF_8);
		data.readerIndex(index+len+1);
		return str;
	}
	
	public static ISerializable readObject(ChannelBuffer data) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		String name = readString(data);
		Class<?> cl = Class.forName("data."+name);
		ISerializable ret = (ISerializable)cl.newInstance();
		if (ret == null) return null;
		ret.unserialize(data);
		return ret;
	}
	
	public static void writeObject(ChannelBuffer buf, ISerializable data) {
		String name = data.getClass().getName();
		name = name.substring(name.lastIndexOf('.'));
		writeString(buf, name);
		data.unserialize(buf);
	}
	
	public static int[] readIntArray(ChannelBuffer data) {
		int size = data.readInt();
		int[] result = new int[size];
		for (int i = 0; i < size; i++) {
			result[i] = data.readInt();
		}
		return result;
	}
	
	public static String[] readStringArray(ChannelBuffer data) {
		int size = data.readInt();
		String[] result = new String[size];
		for (int i = 0; i < size; i++) {
			result[i] = readString(data);
		}
		return result;
	}
	
	public static void writeString(ChannelBuffer buf, String str) {
		byte[] bytes = str.getBytes(CharsetUtil.UTF_8);
		buf.writeShort(bytes.length);
		buf.writeBytes(bytes);
		buf.writeByte(0);
	}
	
	public static void writeBool(ChannelBuffer buf, boolean val) {
		buf.writeByte(val?1:0);
	}
	
	public static void writeRPCParamInt(ChannelBuffer buf, int i) {
		buf.writeByte(Protocol.TYPE_INT);
		buf.writeInt(i);
	}
	
	public static void writeRPCParamObject(ChannelBuffer buf, ISerializable obj) {
		buf.writeByte(Protocol.TYPE_OBJECT);
		Protocol.writeObject(buf, obj);
	}

	public static void writeRPCParamString(ChannelBuffer buf, String str) {
		buf.writeByte(Protocol.TYPE_STRING);
		writeString(buf, str);
	}
	
	public static Object[] readRPCParamList(ChannelBuffer data) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    	int size = data.readByte();
    	int type;
    	Object[] args = new Object[size+1];
    	for (int i = 1; i <= size; i++) {
    		type = data.readByte();
    		switch (type) {
    		case Protocol.TYPE_BYTE:
    			args[i] = data.readByte();
    			break;
    		case Protocol.TYPE_INT:
    			args[i] = data.readInt();
    			break;
    		case Protocol.TYPE_STRING:
    			args[i] = readString(data);
    			break;
    		case Protocol.TYPE_OBJECT:
    			args[i] = readObject(data);
    			break;
    		case Protocol.TYPE_INT_ARRAY:
    			args[i] = readIntArray(data);
    			break;
    		case Protocol.TYPE_STRING_ARRAY:
    			args[i] = readStringArray(data);
    			break;    			
    		}
    	}
    	return args;
	}
	
	
	
}
